﻿/*
 * Copyright 2010 Pieter De Rycke
 *
 * This file is part of Frozen Bubble XNA.
 *
 * Frozen Bubble XNA is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2, as published by the Free Software Foundation.
 *
 * Frozen Bubble XNA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with Frozen Bubble XNA. If not, see 
 * <http://www.gnu.org/licenses/>.
 *
 * Artwork:
 *    Alexis Younes <73lab at free.fr>
 *      (everything but the bubbles)
 *    Amaury Amblard-Ladurantie <amaury at linuxfr.org>
 *      (the bubbles)
 *
 * Soundtrack:
 *    Matthias Le Bidan <matthias.le_bidan at caramail.com>
 *      (the three musics and all the sound effects)
 *
 * Design & Programming:
 *    Guillaume Cottenceau <guillaume.cottenceau at free.fr>
 *      (design and manage the project, whole Perl sourcecode)
 *
 * XNA and Windows Phone 7 port:
 *    Pieter De Rycke
 *
 * Websites:
 *    http://www.frozen-bubble.org/
 *    http://pieterderycke.wordpress.com/
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;

namespace FrozenBubble
{
    public enum PinguinState { Normal, Sleeping, Right, Left, Action, Won, Lost }

    public class PinguinSprite : IScreenComponent
    {
        private GameScreen _screen;
        private bool contentLoaded;

        private int _sleeping;
        private int _moveLatency;
        private int _actionLatency;
        private PinguinState _state;
        private Random _random;
        private IPlayer _player;

        private Texture2D[] _normal;
        private Texture2D _normalCurrent;
        private Texture2D _moveLeft;
        private Texture2D _moveRight;
        private Texture2D _action;
        private Texture2D _sleep;
        private Texture2D[] _lose;
        private Texture2D _loseCurrent;
        private int _loseCurrentIndex;
        private Texture2D[] _won;
        private Texture2D _wonCurrent;
        private int _wonCurrentIndex;

        private const int wonRollBackIndex = 3;
        private const int loseRollBackIndex = 4;

        public PinguinSprite(GameScreen screen, IPlayer player)
        {
            _screen = screen;
            _player = player;
            _random = new Random();
        }

        public void LoadContent()
        {
#if DEBUG
            long start = DateTime.Now.Ticks;
#endif

            // Load Textures
            _normal = _screen.Cache.PinguinNormal;
            _normalCurrent = _normal[0];

            _moveLeft = _screen.Cache.PinguinMoveLeft;
            _moveRight = _screen.Cache.PinguinMoveRight;
            _action = _screen.Cache.PinguinAction;
            _sleep = _screen.Cache.PinguinSleep;

            _lose = _screen.Cache.PinguinLoose;
            _loseCurrent = _lose[0];

            _won = _screen.Cache.PinguinWin;
            _wonCurrent = _won[0];

            contentLoaded = true;

#if DEBUG
            long loadTime = (DateTime.Now.Ticks - start) / 10000;
            Debug.WriteLine("Loadtime PinguinSprite.cs: " + loadTime);
#endif
        }

        public void UnloadContent() { }

        public void Update(GameTime gameTime)
        {
            if (_player.State == GameState.Game)
            {
                KeyboardState keyboard = Keyboard.GetState();

                if (!keyboard.IsKeyDown(Keys.Left) && !keyboard.IsKeyDown(Keys.Right)
                    && !keyboard.IsKeyDown(Keys.Space))
                {
                    _sleeping++;
                }
                else
                {
                    _sleeping = 0;
                    _moveLatency = -20;
                }

                if (_sleeping > BubbleConstants.TIMEOUT_PINGUIN_SLEEP)
                    _state = PinguinState.Sleeping;
                else if (_state == PinguinState.Sleeping)
                    _state = PinguinState.Normal;

                if (_state == PinguinState.Right && !keyboard.IsKeyDown(Keys.Right)
                    || _state == PinguinState.Left && !keyboard.IsKeyDown(Keys.Left)
                    || _state == PinguinState.Action && _actionLatency++ > 5)
                {
                    _state = PinguinState.Normal;
                }

                if (keyboard.IsKeyDown(Keys.Right))
                    _state = PinguinState.Right;

                if (keyboard.IsKeyDown(Keys.Left))
                    _state = PinguinState.Left;

                if (keyboard.IsKeyDown(Keys.Space))
                {
                    _state = PinguinState.Action;
                    _actionLatency = 0;
                }

                if (_state == PinguinState.Normal && _moveLatency++ > 10)
                {
                    _moveLatency = 0;
                    if (_random.NextDouble() < 0.4)
                    {
                        _normalCurrent = _normal[_random.Next(_normal.Length)];
                    }
                }
            }
            else if (_player.State == GameState.Lost)
            {
                _state = PinguinState.Lost;

                if(_moveLatency++ > 5)
                {
                    _moveLatency = 0;
                    _loseCurrentIndex++;
                    if (_loseCurrentIndex >= _lose.Length)
                        _loseCurrentIndex = loseRollBackIndex;

                    _loseCurrent = _lose[_loseCurrentIndex];
                }
            }
            else if (_player.State == GameState.Won)
            {
                _state = PinguinState.Won;

                if (_moveLatency++ > 5)
                {
                    _moveLatency = 0;
                    _wonCurrentIndex++;
                    if (_wonCurrentIndex >= _won.Length)
                        _wonCurrentIndex = wonRollBackIndex;

                    _wonCurrent = _won[_wonCurrentIndex];
                }
            }
        }

        public Texture2D Texture
        {
            get
            {
                switch (_state)
                {
                    case PinguinState.Left:
                        return _moveLeft;
                    case PinguinState.Right:
                        return _moveRight;
                    case PinguinState.Action:
                        return _action;
                    case PinguinState.Sleeping:
                        return _sleep;
                    case PinguinState.Lost:
                        return _loseCurrent;
                    case PinguinState.Won:
                        return _wonCurrent;
                    default:
                        return _normalCurrent;
                }
            }
        }

        public void Reset()
        {
            if (contentLoaded)
            {
                _normalCurrent = _normal[0];
                _loseCurrent = _lose[0];
                _wonCurrent = _won[0];
                _moveLatency = 0;
            }
        }
    }
}
